import 'dart:collection';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';

import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:hixing_app/const/app_config.dart';
import 'package:hixing_app/extensions/str_ext.dart';
import 'package:hixing_app/utils/storage/storage.dart';

class OpenScreenUtil {
  static final OpenScreenUtil _instance = OpenScreenUtil._internal();

  factory OpenScreenUtil() {
    return _instance;
  }

  OpenScreenUtil._internal() {
    init();
  }

  late String screenUrl;

  String _savePath = '';

  void init() {
    screenUrl = AppStorage.appConfigStorage.appOpenScreenUrl ?? "";
  }

  /// 获取视频
  /// 不存在、过期、文件丢失都会重新建立缓存
  // Future<File?> getVideoFile(String url) async {
  //   // 检查是否存在缓存
  //   final CacheVideoModel? cacheVideoModel = checkCache(url);
  //   if (cacheVideoModel != null) {
  //     // 检查缓存是否过期
  //     if (cacheVideoModel.timestamps + cacheMaxTimeStamp <
  //         DateTime.now().millisecondsSinceEpoch) {
  //       // 删除过期的缓存
  //       await removeExpireCache();
  //       // 建立缓存
  //       return startCache(url);
  //     } else {
  //       // 从缓存中获取视频
  //       final File? file = await getVideoFileByCache(url);
  //       if (file == null) {
  //         // 缓存文件丢失，从缓存队列删除
  //         cacheVideoQueue.remove(cacheVideoModel);
  //         // 保存缓存队列
  //         await appVideoCacheStorage.setCacheQueue(cacheVideoQueue);
  //         // 重新建立缓存
  //         return startCache(url);
  //       } else {
  //         return file;
  //       }
  //     }
  //   } else {
  //     // 建立缓存
  //     return startCache(url);
  //   }
  // }

  /// 查找缓存
  // CacheVideoModel? checkCache(String url) {
  //   for (final CacheVideoModel cacheVideoModel in cacheVideoQueue) {
  //     if (cacheVideoModel.url == url) {
  //       return cacheVideoModel;
  //     }
  //   }
  //   return null;
  // }

  Future<void> deleteCacheFile(String url) async {
    final File? file = await getImgFileByCache(url);
    file?.deleteSync();
  }

  /// 建立缓存
  Future<File?> startCache(String url) async {
    // 更新下图片url
    init();
    // 判断图片跟缓存里的是不是同一张，如果是，不处理 直接返回，如果不是，下载图片，更新资源，删除老的图片
    // 如果首次缓存，返回空就行了
    if (screenUrl.isnull) {
      await downloadImg(url);
      return null;
    } else {
      if (url == screenUrl) {
        // 如果传入的图片跟上次缓存的图片是同一张，直接返回文件
        final File? file = await getImgFileByCache(url);
        return file;
      } else {
        // 如果不是同一张，缓存新的图片,删除老的图片,返回得返回上一张的文件
        String oldImg = screenUrl;
        downloadImg(url);
        final File? file = await getImgFileByCache(oldImg);
        return file;
      }
    }
  }

  /// 获取缓存视频储存路径
  Future<String> getSavePath() async {
    if (_savePath.isnull) {
      final Directory appDocumentsPath =
          await getApplicationDocumentsDirectory();
      _savePath = '${appDocumentsPath.path}/cache_open_screen';
    }
    return _savePath;
  }

  /// 获取缓存文件名
  String cacheFileName(String url) {
    final List<int> bytes = utf8.encode(url);
    final md5Str = md5.convert(bytes);
    String fileType = '';
    final list = url.split('.');
    if (list.isNotEmpty) {
      fileType = '.${list.last}';
    }
    return '$md5Str$fileType';
  }

  /// 从缓存里获取视频文件
  Future<File?> getImgFileByCache(String url) async {
    final String savePath = await getSavePath();
    final String fileName = cacheFileName(url);
    final File file = File('$savePath/$fileName');
    final bool isExist = file.existsSync();
    if (isExist) {
      return file;
    } else {
      return null;
    }
  }

  /// 下载视频
  Future<bool> downloadImg(String url) async {
    final savePath = await getSavePath();
    final String fileName = cacheFileName(url);
    try {
      await Dio().download(url, '$savePath/$fileName');
      AppStorage.appConfigStorage.setAppOpenScreenUrl(url);
      if (!screenUrl.isnull && screenUrl != url) {
        // 新老图片不一样。下载新的，删掉老的
        deleteCacheFile(screenUrl);
      }
      return true;
    } catch (e) {
      log(e.toString());
      return false;
    }
  }
}
